import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class CalculatorJavaFX extends Application {

    private TextField display; // 普通计算器显示
    private TextField scientificDisplay; // 科学计算器显示
    private String currentInput = "";
    private double firstNumber = 0;
    private String operator = "";
    private boolean startNewNumber = true;
    private TabPane tabPane;
    
    // 程序员计算器相关变量
    private TextField decDisplay;
    private TextField binDisplay;
    private TextField hexDisplay;
    private long programmerValue = 0;
    private String programmerInput = "";

    @Override
    public void start(Stage primaryStage) {
        // 创建主界面
        createUI(primaryStage);

        // 设置窗口属性
        primaryStage.setTitle("多功能计算器");
        primaryStage.setResizable(false);
        primaryStage.show();
    }

    private void createUI(Stage stage) {
        // 创建标签页面板
        tabPane = new TabPane();
        
        // 普通计算器标签页
        Tab basicTab = new Tab("普通计算器");
        basicTab.setContent(createBasicCalculator());
        basicTab.setClosable(false);
        
        // 程序员计算器标签页
        Tab programmerTab = new Tab("程序员计算器");
        programmerTab.setContent(createProgrammerCalculator());
        programmerTab.setClosable(false);
        
        // 科学计算器标签页
        Tab scientificTab = new Tab("科学计算器");
        scientificTab.setContent(createScientificCalculator());
        scientificTab.setClosable(false);
        
        // 添加标签页到标签面板
        tabPane.getTabs().addAll(basicTab, programmerTab, scientificTab);
        
        // 监听标签页切换事件，动态调整窗口大小
        tabPane.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
            if (newValue == basicTab) {
                stage.setMinWidth(350);
                stage.setMinHeight(450);
                stage.setWidth(350);
                stage.setHeight(450);
            } else if (newValue == programmerTab) {
                stage.setMinWidth(550);
                stage.setMinHeight(650);
                stage.setWidth(550);
                stage.setHeight(650);
            } else if (newValue == scientificTab) {
                stage.setMinWidth(500);
                stage.setMinHeight(600);
                stage.setWidth(500);
                stage.setHeight(600);
            }
        });

        // 创建主布局
        VBox root = new VBox(10);
        root.setPadding(new Insets(10));
        root.getChildren().add(tabPane);

        // 创建场景并设置到舞台
        Scene scene = new Scene(root);
        stage.setScene(scene);
        
        // 设置初始窗口大小（普通计算器）
        stage.setMinWidth(350);
        stage.setMinHeight(450);
        stage.setWidth(350);
        stage.setHeight(450);
    }

    private GridPane createBasicCalculator() {
        // 主布局
        GridPane root = new GridPane();
        root.setAlignment(Pos.CENTER);
        root.setHgap(10);
        root.setVgap(10);
        root.setPadding(new Insets(20, 20, 20, 20));

        // 显示框
        display = new TextField("0");
        display.setEditable(false);
        display.setAlignment(Pos.CENTER_RIGHT);
        display.setFont(javafx.scene.text.Font.font(20));
        display.setPrefHeight(40);
        root.add(display, 0, 0, 4, 1);

        // 按钮标签
        String[][] buttonLabels = {
            {"7", "8", "9", "/"},
            {"4", "5", "6", "*"},
            {"1", "2", "3", "-"},
            {"0", ".", "=", "+"},
            {"AC"}
        };

        // 创建按钮并添加到网格
        for (int row = 0; row < buttonLabels.length; row++) {
            for (int col = 0; col < buttonLabels[row].length; col++) {
                String label = buttonLabels[row][col];
                
                if (label != null && !label.isEmpty()) {
                    Button button = createButton(label, "basic");
                    button.setMinSize(50, 50);
                    root.add(button, col, row + 1);
                    
                    // 如果是最后一个按钮（清除按钮），跨列显示
                    if (row == buttonLabels.length - 1 && col == buttonLabels[row].length - 1) {
                        GridPane.setColumnSpan(button, 4);
                    }
                }
            }
        }
        
        return root;
    }

    private GridPane createProgrammerCalculator() {
        GridPane root = new GridPane();
        root.setAlignment(Pos.CENTER);
        root.setHgap(6);
        root.setVgap(6);
        root.setPadding(new Insets(15, 15, 15, 15));

        // 显示框
        decDisplay = new TextField("0");
        decDisplay.setEditable(false);
        decDisplay.setAlignment(Pos.CENTER_RIGHT);
        decDisplay.setFont(javafx.scene.text.Font.font(14));
        decDisplay.setPrefHeight(30);
        root.add(new Label("十进制:"), 0, 0);
        root.add(decDisplay, 1, 0, 5, 1);

        binDisplay = new TextField("0");
        binDisplay.setEditable(false);
        binDisplay.setAlignment(Pos.CENTER_RIGHT);
        binDisplay.setFont(javafx.scene.text.Font.font(14));
        binDisplay.setPrefHeight(30);
        root.add(new Label("二进制:"), 0, 1);
        root.add(binDisplay, 1, 1, 5, 1);

        hexDisplay = new TextField("0");
        hexDisplay.setEditable(false);
        hexDisplay.setAlignment(Pos.CENTER_RIGHT);
        hexDisplay.setFont(javafx.scene.text.Font.font(14));
        hexDisplay.setPrefHeight(30);
        root.add(new Label("十六进制:"), 0, 2);
        root.add(hexDisplay, 1, 2, 5, 1);

        // 程序员计算器按钮布局 - 增加每行按钮数量
        // 第一行：十六进制字符 A-F
        Button buttonA = createButton("A", "programmer");
        Button buttonB = createButton("B", "programmer");
        Button buttonC = createButton("C", "programmer");
        Button buttonD = createButton("D", "programmer");
        Button buttonE = createButton("E", "programmer");
        Button buttonF = createButton("F", "programmer");
        root.add(buttonA, 0, 3);
        root.add(buttonB, 1, 3);
        root.add(buttonC, 2, 3);
        root.add(buttonD, 3, 3);
        root.add(buttonE, 4, 3);
        root.add(buttonF, 5, 3);

        // 第二行：数字 7-9 和基本运算符
        Button button7 = createButton("7", "programmer");
        Button button8 = createButton("8", "programmer");
        Button button9 = createButton("9", "programmer");
        Button buttonDiv = createButton("/", "programmer");
        Button buttonMul = createButton("*", "programmer");
        Button buttonMod = createButton("%", "programmer");  // 取模运算
        root.add(button7, 0, 4);
        root.add(button8, 1, 4);
        root.add(button9, 2, 4);
        root.add(buttonDiv, 3, 4);
        root.add(buttonMul, 4, 4);
        root.add(buttonMod, 5, 4);

        // 第三行：数字 4-6 和位运算符
        Button button4 = createButton("4", "programmer");
        Button button5 = createButton("5", "programmer");
        Button button6 = createButton("6", "programmer");
        Button buttonAdd = createButton("+", "programmer");
        Button buttonSub = createButton("-", "programmer");
        Button buttonAnd = createButton("&", "programmer");  // 按位与
        root.add(button4, 0, 5);
        root.add(button5, 1, 5);
        root.add(button6, 2, 5);
        root.add(buttonAdd, 3, 5);
        root.add(buttonSub, 4, 5);
        root.add(buttonAnd, 5, 5);

        // 第四行：数字 1-3 和位运算符
        Button button1 = createButton("1", "programmer");
        Button button2 = createButton("2", "programmer");
        Button button3 = createButton("3", "programmer");
        Button buttonLeftParen = createButton("(", "programmer");
        Button buttonRightParen = createButton(")", "programmer");
        Button buttonOr = createButton("|", "programmer");   // 按位或
        root.add(button1, 0, 6);
        root.add(button2, 1, 6);
        root.add(button3, 2, 6);
        root.add(buttonLeftParen, 3, 6);
        root.add(buttonRightParen, 4, 6);
        root.add(buttonOr, 5, 6);

        // 第五行：数字 0 和其他功能按钮
        Button button0 = createButton("0", "programmer");
        Button buttonXor = createButton("^", "programmer");  // 按位异或
        Button buttonNot = createButton("~", "programmer");  // 按位取反
        Button buttonLeftShift = createButton("<<", "programmer");  // 左移
        Button buttonRightShift = createButton(">>", "programmer"); // 右移
        Button buttonClear = createButton("AC", "programmer");
        root.add(button0, 0, 7);
        root.add(buttonXor, 1, 7);
        root.add(buttonNot, 2, 7);
        root.add(buttonLeftShift, 3, 7);
        root.add(buttonRightShift, 4, 7);
        root.add(buttonClear, 5, 7);

        // 第六行：等于和其他功能
        Button buttonEquals = createButton("=", "programmer");
        Button buttonMemoryStore = createButton("MS", "programmer");  // 存储到内存
        Button buttonMemoryRecall = createButton("MR", "programmer"); // 从内存读取
        Button buttonMemoryClear = createButton("MC", "programmer");  // 清除内存
        root.add(buttonEquals, 0, 8, 3, 1);  // 跨3列
        root.add(buttonMemoryStore, 3, 8);
        root.add(buttonMemoryRecall, 4, 8);
        root.add(buttonMemoryClear, 5, 8);
        
        return root;
    }

    private GridPane createScientificCalculator() {
        GridPane root = new GridPane();
        root.setAlignment(Pos.CENTER);
        root.setHgap(8);
        root.setVgap(8);
        root.setPadding(new Insets(20, 20, 20, 20));

        // 显示框
        scientificDisplay = new TextField("0");
        scientificDisplay.setEditable(false);
        scientificDisplay.setAlignment(Pos.CENTER_RIGHT);
        scientificDisplay.setFont(javafx.scene.text.Font.font(20));
        scientificDisplay.setPrefHeight(40);
        root.add(scientificDisplay, 0, 0, 5, 1);

        // 科学计算器按钮
        // 第一行：三角函数和对数函数
        Button sinButton = createButton("sin", "scientific");
        Button cosButton = createButton("cos", "scientific");
        Button tanButton = createButton("tan", "scientific");
        Button logButton = createButton("log", "scientific");
        Button lnButton = createButton("ln", "scientific");
        root.add(sinButton, 0, 1);
        root.add(cosButton, 1, 1);
        root.add(tanButton, 2, 1);
        root.add(logButton, 3, 1);
        root.add(lnButton, 4, 1);

        // 第二行：其他函数
        Button sqrtButton = createButton("sqrt", "scientific");
        Button squareButton = createButton("x²", "scientific");
        Button powerButton = createButton("x^y", "scientific");
        Button leftParenButton = createButton("(", "scientific");
        Button rightParenButton = createButton(")", "scientific");
        root.add(sqrtButton, 0, 2);
        root.add(squareButton, 1, 2);
        root.add(powerButton, 2, 2);
        root.add(leftParenButton, 3, 2);
        root.add(rightParenButton, 4, 2);

        // 第三行：数字 7, 8, 9, 除法运算符, π
        Button button7 = createButton("7", "scientific");
        Button button8 = createButton("8", "scientific");
        Button button9 = createButton("9", "scientific");
        Button divButton = createButton("/", "scientific");
        Button piButton = createButton("π", "scientific");
        root.add(button7, 0, 3);
        root.add(button8, 1, 3);
        root.add(button9, 2, 3);
        root.add(divButton, 3, 3);
        root.add(piButton, 4, 3);

        // 第四行：数字 4, 5, 6, 乘法运算符, e
        Button button4 = createButton("4", "scientific");
        Button button5 = createButton("5", "scientific");
        Button button6 = createButton("6", "scientific");
        Button mulButton = createButton("*", "scientific");
        Button eButton = createButton("e", "scientific");
        root.add(button4, 0, 4);
        root.add(button5, 1, 4);
        root.add(button6, 2, 4);
        root.add(mulButton, 3, 4);
        root.add(eButton, 4, 4);

        // 第五行：数字 1, 2, 3, 减法运算符, 清除
        Button button1 = createButton("1", "scientific");
        Button button2 = createButton("2", "scientific");
        Button button3 = createButton("3", "scientific");
        Button subButton = createButton("-", "scientific");
        Button clearButton = createButton("AC", "scientific");
        root.add(button1, 0, 5);
        root.add(button2, 1, 5);
        root.add(button3, 2, 5);
        root.add(subButton, 3, 5);
        root.add(clearButton, 4, 5);

        // 第六行：数字 0, 小数点, 正负号, 等号, 加法运算符
        Button button0 = createButton("0", "scientific");
        Button dotButton = createButton(".", "scientific");
        Button signButton = createButton("±", "scientific");
        Button equalsButton = createButton("=", "scientific");
        Button addButton = createButton("+", "scientific");
        root.add(button0, 0, 6);
        root.add(dotButton, 1, 6);
        root.add(signButton, 2, 6);
        root.add(equalsButton, 3, 6);
        root.add(addButton, 4, 6);
        
        return root;
    }

    private Button createButton(String label, String type) {
        Button button = new Button(label);
        button.setFont(javafx.scene.text.Font.font(14));
        
        switch (type) {
            case "basic":
                button.setMinSize(50, 50);
                button.setOnAction(e -> handleBasicButtonClick(label));
                break;
            case "programmer":
                button.setMinSize(45, 45);
                button.setOnAction(e -> handleProgrammerButtonClick(label));
                break;
            case "scientific":
                button.setMinSize(50, 50);
                button.setOnAction(e -> handleScientificButtonClick(label));
                break;
        }
        return button;
    }

    private Button createButton(String label) {
        return createButton(label, "basic");
    }

    private void handleBasicButtonClick(String label) {
        if (label.matches("[0-9.]")) { // 数字或小数点
            if (startNewNumber) {
                currentInput = label;
                startNewNumber = false;
            } else {
                currentInput += label;
            }
            updateDisplay();
        } else if (label.equals("+") || label.equals("-") || 
                  label.equals("*") || label.equals("/")) { // 运算符
            if (!currentInput.isEmpty()) {
                firstNumber = Double.parseDouble(currentInput);
                operator = label;
                startNewNumber = true;
            }
        } else if (label.equals("=")) { // 等于号
            if (!operator.isEmpty() && !currentInput.isEmpty()) {
                double secondNumber = Double.parseDouble(currentInput);
                calculateResult(firstNumber, secondNumber, operator);
                operator = "";
                startNewNumber = true;
            }
        } else if (label.equals("AC")) { // 清除
            currentInput = "";
            firstNumber = 0;
            operator = "";
            updateDisplay("0");
        }
    }

    private void handleProgrammerButtonClick(String label) {
        // 处理数字和十六进制字符输入
        if (label.matches("[0-9A-F]")) {
            programmerInput += label;
            try {
                programmerValue = Long.parseLong(programmerInput, 16);
                updateProgrammerDisplays();
            } catch (NumberFormatException e) {
                showError("输入数值过大");
                programmerInput = programmerInput.substring(0, programmerInput.length() - 1);
            }
        } 
        // 清除操作
        else if (label.equals("AC")) {
            programmerValue = 0;
            programmerInput = "";
            updateProgrammerDisplays();
        }
        // 运算符操作
        else if (label.equals("+") || label.equals("-") || label.equals("*") || label.equals("/") ||
                 label.equals("&") || label.equals("|") || label.equals("^") || label.equals("<<") || 
                 label.equals(">>") || label.equals("%")) {
            firstNumber = programmerValue;
            operator = label;
            programmerInput = "";
            startNewNumber = true;
        }
        // 按位取反操作
        else if (label.equals("~")) {
            programmerValue = ~programmerValue;
            programmerInput = Long.toHexString(programmerValue).toUpperCase();
            updateProgrammerDisplays();
        }
        // 括号操作
        else if (label.equals("(") || label.equals(")")) {
            // 程序员计算器中括号主要用于表达式计算，这里简化处理
            programmerInput += label;
        }
        // 等于操作
        else if (label.equals("=")) {
            if (!operator.isEmpty() && !programmerInput.isEmpty()) {
                long secondNumber = Long.parseLong(programmerInput, 16);
                calculateProgrammerResult(firstNumber, secondNumber, operator);
                operator = "";
                startNewNumber = true;
            }
        }
        // 内存操作
        else if (label.equals("MS")) {
            // 存储到内存（简化实现）
            // 实际应用中可以使用一个变量来存储内存值
        }
        else if (label.equals("MR")) {
            // 从内存读取（简化实现）
        }
        else if (label.equals("MC")) {
            // 清除内存（简化实现）
        }
    }

    private void handleScientificButtonClick(String label) {
        if (label.matches("[0-9.]")) { // 数字或小数点
            if (startNewNumber) {
                currentInput = label;
                startNewNumber = false;
            } else {
                currentInput += label;
            }
            updateScientificDisplay();
        } else if (label.equals("AC")) { // 清除
            currentInput = "";
            firstNumber = 0;
            operator = "";
            updateScientificDisplay("0");
        } else if (label.equals("=")) { // 等于号
            if (!operator.isEmpty() && !currentInput.isEmpty()) {
                double secondNumber = Double.parseDouble(currentInput);
                calculateScientificResult(firstNumber, secondNumber, operator);
                operator = "";
                startNewNumber = true;
            }
        } else if (label.equals("+") || label.equals("-") || 
                  label.equals("*") || label.equals("/")) { // 基本运算符
            if (!currentInput.isEmpty()) {
                firstNumber = Double.parseDouble(currentInput);
                operator = label;
                startNewNumber = true;
            }
        } else if (label.equals("sin")) { // 正弦函数
            if (!currentInput.isEmpty()) {
                double value = Double.parseDouble(currentInput);
                double result = Math.sin(Math.toRadians(value));
                currentInput = String.valueOf(result);
                updateScientificDisplay();
                startNewNumber = true;
            }
        } else if (label.equals("cos")) { // 余弦函数
            if (!currentInput.isEmpty()) {
                double value = Double.parseDouble(currentInput);
                double result = Math.cos(Math.toRadians(value));
                currentInput = String.valueOf(result);
                updateScientificDisplay();
                startNewNumber = true;
            }
        } else if (label.equals("tan")) { // 正切函数
            if (!currentInput.isEmpty()) {
                double value = Double.parseDouble(currentInput);
                double result = Math.tan(Math.toRadians(value));
                currentInput = String.valueOf(result);
                updateScientificDisplay();
                startNewNumber = true;
            }
        } else if (label.equals("log")) { // 常用对数
            if (!currentInput.isEmpty()) {
                double value = Double.parseDouble(currentInput);
                if (value > 0) {
                    double result = Math.log10(value);
                    currentInput = String.valueOf(result);
                    updateScientificDisplay();
                    startNewNumber = true;
                } else {
                    showError("对数的真数必须大于0");
                }
            }
        } else if (label.equals("ln")) { // 自然对数
            if (!currentInput.isEmpty()) {
                double value = Double.parseDouble(currentInput);
                if (value > 0) {
                    double result = Math.log(value);
                    currentInput = String.valueOf(result);
                    updateScientificDisplay();
                    startNewNumber = true;
                } else {
                    showError("对数的真数必须大于0");
                }
            }
        } else if (label.equals("sqrt")) { // 平方根
            if (!currentInput.isEmpty()) {
                double value = Double.parseDouble(currentInput);
                if (value >= 0) {
                    double result = Math.sqrt(value);
                    currentInput = String.valueOf(result);
                    updateScientificDisplay();
                    startNewNumber = true;
                } else {
                    showError("负数不能开平方根");
                }
            }
        } else if (label.equals("x²")) { // 平方
            if (!currentInput.isEmpty()) {
                double value = Double.parseDouble(currentInput);
                double result = value * value;
                currentInput = String.valueOf(result);
                updateScientificDisplay();
                startNewNumber = true;
            }
        } else if (label.equals("x^y")) { // 幂运算
            if (!currentInput.isEmpty()) {
                firstNumber = Double.parseDouble(currentInput);
                operator = "^";
                startNewNumber = true;
            }
        } else if (label.equals("±")) { // 正负号
            if (!currentInput.isEmpty() && !currentInput.equals("0")) {
                if (currentInput.startsWith("-")) {
                    currentInput = currentInput.substring(1);
                } else {
                    currentInput = "-" + currentInput;
                }
                updateScientificDisplay();
            }
        } else if (label.equals("π")) { // 圆周率
            currentInput = String.valueOf(Math.PI);
            updateScientificDisplay();
            startNewNumber = true;
        } else if (label.equals("e")) { // 自然常数
            currentInput = String.valueOf(Math.E);
            updateScientificDisplay();
            startNewNumber = true;
        }
    }

    private void updateDisplay() {
        updateDisplay(currentInput);
    }

    private void updateDisplay(String text) {
        if (display != null) {
            display.setText(text);
        }
    }

    private void updateScientificDisplay() {
        updateScientificDisplay(currentInput);
    }

    private void updateScientificDisplay(String text) {
        if (scientificDisplay != null) {
            scientificDisplay.setText(text);
        }
    }

    private void updateProgrammerDisplays() {
        if (decDisplay != null) decDisplay.setText(String.valueOf(programmerValue));
        if (binDisplay != null) binDisplay.setText(Long.toBinaryString(programmerValue));
        if (hexDisplay != null) hexDisplay.setText(Long.toHexString(programmerValue).toUpperCase());
    }

    private void calculateResult(double num1, double num2, String op) {
        double result = 0;
        boolean error = false;

        switch (op) {
            case "+":
                result = num1 + num2;
                break;
            case "-":
                result = num1 - num2;
                break;
            case "*":
                result = num1 * num2;
                break;
            case "/":
                if (num2 != 0) {
                    result = num1 / num2;
                } else {
                    showError("错误：不能除以零");
                    error = true;
                }
                break;
        }

        if (!error) {
            currentInput = Double.toString(result);
            updateDisplay();
        }
    }

    private void calculateScientificResult(double num1, double num2, String op) {
        double result = 0;
        boolean error = false;

        switch (op) {
            case "+":
                result = num1 + num2;
                break;
            case "-":
                result = num1 - num2;
                break;
            case "*":
                result = num1 * num2;
                break;
            case "/":
                if (num2 != 0) {
                    result = num1 / num2;
                } else {
                    showError("错误：不能除以零");
                    error = true;
                }
                break;
            case "^":
                result = Math.pow(num1, num2);
                break;
        }

        if (!error) {
            currentInput = Double.toString(result);
            updateScientificDisplay();
        }
    }

    private void calculateProgrammerResult(double num1, double num2, String op) {
        long result = 0;
        boolean error = false;

        switch (op) {
            case "+":
                result = (long)num1 + (long)num2;
                break;
            case "-":
                result = (long)num1 - (long)num2;
                break;
            case "*":
                result = (long)num1 * (long)num2;
                break;
            case "/":
                if (num2 != 0) {
                    result = (long)num1 / (long)num2;
                } else {
                    showError("错误：不能除以零");
                    error = true;
                }
                break;
            case "%":  // 取模运算
                if (num2 != 0) {
                    result = (long)num1 % (long)num2;
                } else {
                    showError("错误：不能除以零");
                    error = true;
                }
                break;
            case "&":  // 按位与
                result = (long)num1 & (long)num2;
                break;
            case "|":  // 按位或
                result = (long)num1 | (long)num2;
                break;
            case "^":  // 按位异或
                result = (long)num1 ^ (long)num2;
                break;
            case "<<":  // 左移
                result = (long)num1 << (long)num2;
                break;
            case ">>":  // 右移
                result = (long)num1 >> (long)num2;
                break;
        }

        if (!error) {
            programmerValue = result;
            programmerInput = Long.toHexString(programmerValue).toUpperCase();
            updateProgrammerDisplays();
        }
    }

    private void showError(String message) {
        Alert alert = new Alert(Alert.AlertType.ERROR);
        alert.setTitle("错误");
        alert.setHeaderText(null);
        alert.setContentText(message);
        alert.showAndWait();
    }

    public static void main(String[] args) {
        launch(args);
    }
}